package util

import (
	"errors"
	"github.com/unknwon/com"
	"sync"
	"time"
)

// 常量定义
const (
	workerBits  uint8 = 10                      // 工作节点 ID 所占位数
	numberBits  uint8 = 12                      // 序列号所占位数
	workerMax   int64 = -1 ^ (-1 << workerBits) // 工作节点 ID 的最大值
	numberMax   int64 = -1 ^ (-1 << numberBits) // 序列号的最大值
	timeShift   uint8 = workerBits + numberBits // 时间戳左移的位数
	workerShift uint8 = numberBits              // 工作节点 ID 左移的位数
	startTime   int64 = 1710303567629           // 自定义的时间起点（毫秒），用于防止生成相同的 ID
)

// Worker 定义雪花算法的工作节点。
// 包含互斥锁、时间戳、工作节点 ID 和序列号。
type Worker struct {
	mu        sync.Mutex // 互斥锁，确保并发安全
	timestamp int64      // 上次生成 ID 的时间戳
	workerId  int64      // 工作节点 ID
	number    int64      // 序列号
}

// newWorker 创建一个新的工作节点实例。
// workerId: 工作节点 ID。
// 返回值:
// - *Worker: 指向新创建的工作节点的指针。
// - error: 如果工作节点 ID 超出范围，则返回错误。
func newWorker(workerId int64) (*Worker, error) {
	if workerId < 0 || workerId > workerMax {
		return nil, errors.New("工作节点 ID 超出范围")
	}
	// 初始化并返回新的工作节点实例。
	return &Worker{
		timestamp: 0,
		workerId:  workerId,
		number:    0,
	}, nil
}

// getId 生成一个唯一的 ID。
// 使用雪花算法生成包含时间戳、工作节点 ID 和序列号的唯一 ID。
// 返回值:
// - int64: 生成的唯一 ID。
func (w *Worker) getId() int64 {
	w.mu.Lock()
	defer w.mu.Unlock()

	now := time.Now().UnixNano() / 1e6 // 获取当前时间戳（毫秒）

	// 如果当前时间戳与上次相同，则增加序列号
	if w.timestamp == now {
		w.number++
		if w.number > numberMax { // 如果序列号超出最大值，等待直到下一个时间戳
			for now <= w.timestamp {
				now = time.Now().UnixNano() / 1e6
			}
		}
	} else {
		w.number = 0 // 如果时间戳不同，重置序列号为 0
		w.timestamp = now
	}

	// 组合时间戳、工作节点 ID 和序列号生成唯一 ID
	ID := int64((now-startTime)<<timeShift | (w.workerId << workerShift) | (w.number))
	return ID
}

var UitlSnow = uitlSnow{}

type uitlSnow struct{}

func (us uitlSnow) SnowId() string {

	var workerId int64
	workerId = 1
	snow, _ := newWorker(workerId)
	return com.ToStr(snow.getId())
}
